From f9fdc76407785932a1b3e909f608a2b325471a93 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Thu, 26 Jan 2017 09:09:07 -0800 Subject: [PATCH] More improvements Use Context::target_filenames rather than trying to redo that. Traverse path dependencies recursively, so we get transitive deps. Use existing fingerprint parsing. --- src/cargo/ops/cargo_rustc/fingerprint.rs | 12 +- src/cargo/ops/cargo_rustc/output_depinfo.rs | 131 +++++--------------- 2 files changed, 44 insertions(+), 99 deletions(-) diff --git a/src/cargo/ops/cargo_rustc/fingerprint.rs b/src/cargo/ops/cargo_rustc/fingerprint.rs index 02ea5a47f..d892a6517 100644 --- a/src/cargo/ops/cargo_rustc/fingerprint.rs +++ b/src/cargo/ops/cargo_rustc/fingerprint.rs @@ -563,7 +563,8 @@ fn log_compare(unit: &Unit, compare: &CargoResult<()>) { } } -fn dep_info_mtime_if_fresh(dep_info: &Path) -> CargoResult> { +// Parse the dep-info into a list of paths +pub fn parse_dep_info(dep_info: &Path) -> CargoResult>> { macro_rules! fs_try { ($e:expr) => (match $e { Ok(e) => e, Err(..) => return Ok(None) }) } @@ -600,8 +601,15 @@ fn dep_info_mtime_if_fresh(dep_info: &Path) -> CargoResult> { } paths.push(cwd.join(&file)); } + Ok(Some(paths)) +} - Ok(mtime_if_fresh(&dep_info, paths.iter())) +fn dep_info_mtime_if_fresh(dep_info: &Path) -> CargoResult> { + if let Some(paths) = parse_dep_info(dep_info)? { + Ok(mtime_if_fresh(&dep_info, paths.iter())) + } else { + Ok(None) + } } fn pkg_fingerprint(cx: &Context, pkg: &Package) -> CargoResult { diff --git a/src/cargo/ops/cargo_rustc/output_depinfo.rs b/src/cargo/ops/cargo_rustc/output_depinfo.rs index 7c8ac3276..add28e023 100644 --- a/src/cargo/ops/cargo_rustc/output_depinfo.rs +++ b/src/cargo/ops/cargo_rustc/output_depinfo.rs @@ -1,23 +1,11 @@ -use std::borrow::ToOwned; use std::collections::HashSet; -use std::io::{Read, Write}; +use std::io::Write; use std::fs::File; use std::path::{Path, PathBuf}; -use core::{TargetKind}; use ops::{Context, Unit}; -use util::{CargoResult, internal, human}; - -#[derive(Debug)] -struct DepLine { - target: String, - deps: Vec, -} - -struct DepFile { - dir: String, - deps: Vec, -} +use util::{CargoResult, internal}; +use ops::cargo_rustc::fingerprint; fn render_filename>(path: P, basedir: Option<&str>) -> CargoResult { let path = path.as_ref(); @@ -28,101 +16,50 @@ fn render_filename>(path: P, basedir: Option<&str>) -> CargoResul _ => path, } }; - relpath.to_str().ok_or(internal("path not utf-8")).map(ToOwned::to_owned) + relpath.to_str().ok_or(internal("path not utf-8")).map(|f| f.replace(" ", "\\ ")) } -fn read_dep_file>(path: P) -> CargoResult { - let mut file = File::open(&path).map_err(|_| - human("error opening ".to_string() + path.as_ref().to_str().unwrap_or("(bad unicode")))?; - let mut contents = String::new(); - let _ = file.read_to_string(&mut contents)?; - let mut spl = contents.split('\0'); - let dir = spl.next().ok_or(internal("dependency file empty"))?; - let dep_txt = spl.next().ok_or(internal("dependency file missing null byte"))?; - let mut result = Vec::new(); - for line in dep_txt.lines() { - let mut line_spl = line.split(": "); - if let Some(target) = line_spl.next() { - if let Some(deps) = line_spl.next() { - let deps = deps.split_whitespace().map(ToOwned::to_owned).collect(); - result.push(DepLine { - target: target.to_string(), - deps: deps, - }); - } - } +fn add_deps_for_unit<'a, 'b>(deps: &mut HashSet, context: &mut Context<'a, 'b>, + unit: &Unit<'a>, visited: &mut HashSet>) -> CargoResult<()> +{ + if visited.contains(unit) { + return Ok(()); } - Ok(DepFile { - dir: dir.to_string(), - deps: result, - }) -} + visited.insert(unit.clone()); -fn add_deps(depfile: &DepFile, deps: &mut HashSet) { - let dep_dir = PathBuf::from(&depfile.dir); - for depline in &depfile.deps { - for dep in &depline.deps { - deps.insert(dep_dir.join(dep)); + let dep_info_loc = fingerprint::dep_info_loc(context, unit); + if let Some(paths) = fingerprint::parse_dep_info(&dep_info_loc)? { + for path in paths { + deps.insert(path); } } -} - -// TODO: probably better to use Context::target_filenames for this -fn target_filename(context: &mut Context, unit: &Unit) -> CargoResult { - let (dir, base) = context.link_stem(&unit).ok_or(internal("can't get link stem"))?; - if unit.target.is_lib() { - Ok(dir.join(["lib", &base, ".rlib"].concat())) - } else { - Ok(dir.join(base)) - } -} -fn add_deps_for_unit(deps: &mut HashSet, context: &mut Context, unit: &Unit) - -> CargoResult<()> -{ - // TODO: this is duplicated against filename in fingerprint.rs - let kind = match *unit.target.kind() { - TargetKind::Lib(..) => "lib", - TargetKind::Bin => "bin", - TargetKind::Test => "integration-test", - TargetKind::ExampleBin | - TargetKind::ExampleLib(..) => "example", - TargetKind::Bench => "bench", - TargetKind::CustomBuild => "build-script", - }; - let flavor = if unit.profile.test { - "test-" - } else if unit.profile.doc { - "doc-" - } else { - "" - }; - let dep_filename = ["dep-", flavor, kind, "-", &context.file_stem(&unit)].concat(); - let path = context.fingerprint_dir(&unit).join(&dep_filename); - let depfile = read_dep_file(&path)?; - add_deps(&depfile, deps); - Ok(()) -} - -pub fn output_depinfo(context: &mut Context, unit: &Unit) -> CargoResult<()> { - let mut deps = HashSet::new(); - add_deps_for_unit(&mut deps, context, unit)?; + // recursively traverse all transitive dependencies for dep_unit in &context.dep_targets(unit)? { let source_id = dep_unit.pkg.package_id().source_id(); if source_id.is_path() { - add_deps_for_unit(&mut deps, context, dep_unit)?; + add_deps_for_unit(deps, context, dep_unit, visited)?; } } - let filename = target_filename(context, unit)?; - let mut output_path = filename.clone().into_os_string(); - output_path.push(".d"); + Ok(()) +} + +pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) -> CargoResult<()> { + let mut deps = HashSet::new(); + let mut visited = HashSet::new(); + add_deps_for_unit(&mut deps, context, unit, &mut visited)?; let basedir = None; // TODO - let target_fn = render_filename(filename, basedir)?; - let mut outfile = File::create(output_path)?; - write!(outfile, "{}:", target_fn)?; - for dep in &deps { - write!(outfile, " {}", render_filename(dep, basedir)?)?; + for (_filename, link_dst, _linkable) in context.target_filenames(unit)? { + if let Some(link_dst) = link_dst { + let output_path = link_dst.with_extension("d"); + let target_fn = render_filename(link_dst, basedir)?; + let mut outfile = File::create(output_path)?; + write!(outfile, "{}:", target_fn)?; + for dep in &deps { + write!(outfile, " {}", render_filename(dep, basedir)?)?; + } + writeln!(outfile, "")?; + } } - writeln!(outfile, "")?; Ok(()) } -- 2.30.2